// Package config 提供应用程序配置加载功能，支持环境变量覆盖。
package config

import (
	"encoding/json"
	"os"
	"strconv"
	"sync"
	"time"
)

// Config 表示完整的应用程序配置结构。
type Config struct {
	SystemName   string         `json:"system-name"`
	DBInfo       DBConfig       `json:"db-info"`
	RedisInfo    RedisConfig    `json:"redis-info"`
	RabbitMQInfo RabbitMQConfig `json:"rabbitmq-info"`
	WechatPay    WechatConfig   `json:"wechatpay-info"`
	Auth         AuthConfig     `json:"auth"`
	Sentry       SentryConfig   `json:"sentry"`
}

// DBConfig 持有数据库相关设置。
type DBConfig struct {
	Host     string `json:"host"`
	Port     int    `json:"port"`
	User     string `json:"username"`
	Password string `json:"password"`
	DBName   string `json:"database"`
	SSLMode  string `json:"sslmode"`
}

// RedisConfig 持有 Redis 相关设置。
type RedisConfig struct {
	Host string `json:"host"`
	Port int    `json:"port"`
}

// RabbitMQConfig 持有 RabbitMQ 相关设置。
type RabbitMQConfig struct {
	Host     string `json:"host"`
	Port     int    `json:"port"`
	Username string `json:"username"`
	Password string `json:"password"`
}

// WechatConfig 持有微信支付相关设置。
type WechatConfig struct {
	AppID           string `json:"sp_appid"`
	BundleID        string `json:"bundle_id"` // Fixed typo from "boundle_id"
	MchID           string `json:"mch_id"`
	APIv3Key        string `json:"api_v3_key"`
	SerialNo        string `json:"serial_no"`
	NotifyURL       string `json:"notify_url"`
	PrivateKeyPEM   string `json:"mch_private_key"`
	RetryMax        int    `json:"retry_max"`
	RetryBaseMillis int    `json:"retry_base_ms"`
	RetryMaxMillis  int    `json:"retry_max_ms"`
	// Deprecated fields for backward compatibility
	SpKey     string `json:"sp_key"`     // Maps to APIv3Key
	BoundleID string `json:"boundle_id"` // Maps to BundleID (typo preserved for compatibility)
}

// AuthConfig 持有 API 认证配置。
type AuthConfig struct {
	APIKeys        map[string]string `json:"api_keys"`
	SigningSecrets map[string]string `json:"signing_secrets"`
}

type SentryConfig struct {
	Dsn         string  `json:"dsn"`
	Environment string  `json:"environment"`
	SampleRate  float64 `json:"sample_rate"`
}

var (
	cfg  *Config
	once sync.Once
	mu   sync.RWMutex
)

// Get 返回从文件加载并被环境变量覆盖的单例配置。
func Get() *Config {
	once.Do(func() {
		cfg = &Config{}
		// Load from file if exists
		if data, err := os.ReadFile("system-config.json"); err == nil {
			_ = json.Unmarshal(data, cfg)
		}
		// Apply environment overrides
		applyEnvOverrides(cfg)
		go watchAndReload()
	})
	mu.RLock()
	defer mu.RUnlock()
	return cfg
}

func applyEnvOverrides(c *Config) {
	// Database
	if v := os.Getenv("DB_HOST"); v != "" {
		c.DBInfo.Host = v
	}
	if v := os.Getenv("DB_PORT"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			c.DBInfo.Port = n
		}
	}
	if v := os.Getenv("DB_USER"); v != "" {
		c.DBInfo.User = v
	}
	if v := os.Getenv("DB_PASSWORD"); v != "" {
		c.DBInfo.Password = v
	}
	if v := os.Getenv("DB_NAME"); v != "" {
		c.DBInfo.DBName = v
	}
	if v := os.Getenv("DB_SSLMODE"); v != "" {
		c.DBInfo.SSLMode = v
	}

	// Redis
	if v := os.Getenv("REDIS_HOST"); v != "" {
		c.RedisInfo.Host = v
	}
	if v := os.Getenv("REDIS_PORT"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			c.RedisInfo.Port = n
		}
	}

	// RabbitMQ
	if v := os.Getenv("RABBITMQ_HOST"); v != "" {
		c.RabbitMQInfo.Host = v
	}
	if v := os.Getenv("RABBITMQ_PORT"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			c.RabbitMQInfo.Port = n
		}
	}
	if v := os.Getenv("RABBITMQ_USERNAME"); v != "" {
		c.RabbitMQInfo.Username = v
	}
	if v := os.Getenv("RABBITMQ_PASSWORD"); v != "" {
		c.RabbitMQInfo.Password = v
	}

	// 微信支付 - 应用环境变量配置，优先级正确
	if v := os.Getenv("WECHAT_APP_ID"); v != "" {
		c.WechatPay.AppID = v
	}
	if v := os.Getenv("WECHAT_MCH_ID"); v != "" {
		c.WechatPay.MchID = v
	}
	if v := os.Getenv("WECHAT_SERIAL_NO"); v != "" {
		c.WechatPay.SerialNo = v
	}
	if v := os.Getenv("WECHAT_API_V3_KEY"); v != "" {
		c.WechatPay.APIv3Key = v
	}
	if v := os.Getenv("WECHAT_NOTIFY_URL"); v != "" {
		c.WechatPay.NotifyURL = v
	}
	if v := os.Getenv("WECHAT_MCH_PRIVATE_KEY"); v != "" {
		c.WechatPay.PrivateKeyPEM = v
	}
	if v := os.Getenv("WECHAT_RETRY_MAX"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			c.WechatPay.RetryMax = n
		}
	}
	if v := os.Getenv("WECHAT_RETRY_BASE_MS"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			c.WechatPay.RetryBaseMillis = n
		}
	}
	if v := os.Getenv("WECHAT_RETRY_MAX_MS"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			c.WechatPay.RetryMaxMillis = n
		}
	}

	// Handle backward compatibility and field mapping
	applyWechatFieldMapping(&c.WechatPay)
}

// applyWechatFieldMapping 处理微信配置的向后兼容性
func applyWechatFieldMapping(w *WechatConfig) {

	// 将废弃的 sp_key 映射到 APIv3Key，如果 APIv3Key 为空
	if w.APIv3Key == "" && w.SpKey != "" {
		w.APIv3Key = w.SpKey
	}

	// 将废弃的 boundle_id 映射到 BundleID，如果 BundleID 为空
	if w.BundleID == "" && w.BoundleID != "" {
		w.BundleID = w.BoundleID
	}
	// Set default values if not configured
	if w.RetryMax <= 0 {
		w.RetryMax = 3
	}
	if w.RetryBaseMillis <= 0 {
		w.RetryBaseMillis = 200
	}
	if w.RetryMaxMillis <= 0 {
		w.RetryMaxMillis = 2000
	}
}

// watchAndReload 执行简单的定期重载 system-config.json 文件
func watchAndReload() {
	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop()
	for range ticker.C {
		var newCfg Config
		if data, err := os.ReadFile("system-config.json"); err == nil {
			if err := json.Unmarshal(data, &newCfg); err == nil {
				applyEnvOverrides(&newCfg)
				mu.Lock()
				cfg = &newCfg
				mu.Unlock()
			}
		}
	}
}
